﻿using AnyCAD.Foundation;
using AnyCAD.NX.Common;
using AnyCAD.NX.IO.DXF;
using AnyCAD.NX.ViewModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Rapid.Sketch.Plugin.Command;
using Rapid.Sketch.Plugin.Model;
using Rapid.Sketch.Plugin.Tag;
using System.Text.Json;
using System.Windows.Input;

namespace Rapid.Sketch.Plugin.ViewModel
{
    internal class SketchViewModel : ObservableObject
    {

        AsycIpcServer mIpcServer;
        public SketchViewModel()
        {
            NewLine = new RelayCommand(OnNewLine);
            NewArc = new RelayCommand(OnNewArc);
            NewCircle = new RelayCommand(OnNewCirlce);
            NewEllipse = new RelayCommand(OnNewEllipse);
            ImportDXF = new RelayCommand(OnImportDXF);
            NewSectionBar = new RelayCommand(OnNewSectionBar);
            PointCloud = new RelayCommand(OnPointCloud);
            AddTag = new RelayCommand(OnAddTag);

            mIpcServer = new AsycIpcServer("pcl.anycad", "anycad.pcl");
        }

        public ICommand PointCloud { get; set; }


        void OnPointCloud()
        {
            var dlg = new Microsoft.Win32.OpenFileDialog
            {
                DefaultExt = ".pcd",
                Filter = "PointCloud Files (*.pcd)|*.pcd"
            };
            var result = dlg.ShowDialog();
            if (result != true)
                return;

            var filename = dlg.FileName;

            LoadPointCloud command = new LoadPointCloud
            {
                FileName = filename
            };


            mIpcServer.Send(command);

            mIpcServer.Run((string command, string parameter) =>
            {
                var result = JsonSerializer.Deserialize<LoadPointCloudResult>(parameter);
                if (result != null)
                {
                    var meshNode = SharedShapeNode.Create(result.Name, result.Size);
                    if (meshNode != null)
                    {
                        //meshNode.SetTransform(Matrix4.makeScale(500, 500, 500));
                        var viewer3D = MainViewModel.Instance.Viewer;
                        viewer3D?.GetContext().GetScene().AddNode(meshNode);
                    }
                }
            });
        }

        public void Unload()
        {
            mIpcServer.Exit();
        }

        public ICommand NewLine { get; set; }
        void OnNewLine()
        {
            AnyCAD.Foundation.Application.Instance().ExecuteCommand("Line");
        }

        public ICommand NewArc { get; set; }
        void OnNewArc()
        {
            AnyCAD.Foundation.Application.Instance().ExecuteCommand("Arc");
        }

        public ICommand NewCircle { get; set; }
        void OnNewCirlce()
        {
            AnyCAD.Foundation.Application.Instance().ExecuteCommand("Circle");
        }
        public ICommand NewEllipse { get; set; }
        void OnNewEllipse()
        {
            var viewer3D = MainViewModel.Instance.ViewContext;
            var arc1 = SketchBuilder.MakeArcOfCircle(new GPnt(0, 2, 0), new GPnt(10, 0, 0), new GPnt(5, 5, 0));
            var arc2 = SketchBuilder.MakeArcOfCircle(new GPnt(0, 2, 0), new GPnt(-10, 0, 0), new GPnt(-5, 5, 0));
            var bottomPt = new GPnt(0, -12, 0);
            var line1 = SketchBuilder.MakeLine(new GPnt(-10, 0, 0), bottomPt);
            var line2 = SketchBuilder.MakeLine(bottomPt, new GPnt(10, 0, 0));

            var shapeList = new TopoShapeList
                        {
                            arc1,
                            arc2,
                            line1,
                            line2
                        };

            var wire = SketchBuilder.MakeWire(shapeList);
            var face = SketchBuilder.MakePlanarFace(wire);
            var shape = FeatureTool.Extrude(face, 5, GP.DZ());

            shape = FeatureTool.Fillet(shape, 1);
            var node = new BrepSceneNode(shape, null, null, 0);
            viewer3D.GetScene().AddNode(node);
        }
        public ICommand ImportDXF { get; set; }
        void OnImportDXF()
        {
            var viewer3D = MainViewModel.Instance.ViewContext;
            var dlg = new Microsoft.Win32.OpenFileDialog
            {
                DefaultExt = ".dxf",
                Filter = "DXF Files (*.dxf)|*.dxf"
            };
            var result = dlg.ShowDialog();
            if (result == true)
            {
                var filename = dlg.FileName;

                var shapes = DxfIO.Load(filename, 1);
                foreach (var shape in shapes)
                {
                    var node = new BrepSceneNode(shape, null, null, 0);
                    viewer3D.GetScene().AddNode(node);
                }
            }
        }
        public ICommand NewSectionBar { get; set; }
        void OnNewSectionBar()
        {
            AnyCAD.Foundation.Application.Instance().ExecuteCommand("PICK");

            var doc = AnyCAD.Foundation.Application.Instance().GetActiveDocument();

            var undo = new UndoTransaction(doc);
            undo.Start("Tube");
            SectionBarModel.NewInstance(doc, "Bar");
            undo.Commit();
        }

        public ICommand AddTag { get; set; }
        void OnAddTag()
        {
            var doc = AnyCAD.Foundation.Application.Instance().GetActiveDocument();

            var undo = new UndoTransaction(doc);
            undo.Start("Tag");
            var store = ElementSchemaManager.Instance().CreateInstance(nameof(UserTagModel), "Tag", doc);
            var model = new UserTagModel();
            model.Load(store);
            model.Content = "AnyCAD RapidCAX!";
            model.Position = new GPnt(10, 10, 100);
            model.Save(store);
            undo.Commit();
        }
    }
}
